package com.pzr.soccer.service.impl;

import com.pzr.soccer.model.*;
import com.pzr.soccer.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.pzr.soccer.constans.Consts;
import com.pzr.soccer.service.LoginAndRegistryService;
import com.pzr.soccer.service.RoleService;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author pzr
 * @date:2021-12-21-15:34
 * @Description:
 **/
@Slf4j
@Service
public class LoginAndRegistryServiceImpl implements LoginAndRegistryService{
    @Value("${basic.token.outside:Basic Y2xpZW50OjEyMzQ1Ng==}")
    private String basicTokeNormal;
    @Value("${basic.token.outside:Basic c29jY2VyLWNsaWVudDpzb2NjZXItc2VjcmV0}")
    private String basicTokeSoccer;
    @Value("${auth.client.soccer:soccer}")
    private String client;
    
    @Value("${oauth2.token.url:http://localhost:8000/oauth/token}")
    private String oauth2Url;
    
    private Map<String, String> basiAuths=Map.of("soccer","Basic c29jY2VyLWNsaWVudDpzb2NjZXItc2VjcmV0","normal","Basic Y2xpZW50OjEyMzQ1Ng==");

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    RestTemplate customRestTemplate;
    
    @Autowired
    MongoOperations mongoOperations;
    @Autowired
    RoleService roleService;

 
    @Override
    public LoginResult  login(LoginOrRegistryForm form) {
        //构建rest请求
        HttpHeaders headers=new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        LinkedMultiValueMap<String ,Object> multiValueMap=new LinkedMultiValueMap<>();
        multiValueMap.add("username",form.getUsername());
        multiValueMap.add("password",form.getPassword());
        multiValueMap.add("grant_type","password");
        multiValueMap.add("client", client);

        if(form.getClient()==null||!basiAuths.containsKey(form.getClient())) {
        	return null;
        }
      
        
        headers.add("Authorization",basiAuths.get(form.getClient()));

        HttpEntity<LinkedMultiValueMap<String,Object>> entity=new HttpEntity<>(multiValueMap,headers);
        System.out.println("发送获取token请求！");
        ResponseEntity<JwtToken> jwtTokenResp=null;

        //处理用户密码错
        try {
            jwtTokenResp=customRestTemplate.postForEntity(oauth2Url,entity,JwtToken.class);
        }
        catch (Exception e){
            log.error(form.getUsername()+" get token failed");
            log.info(String.format("other error:%s message:%s",e.getClass().getSimpleName(),e.getMessage()));
                    if(e.getMessage().contains("用户名或密码错误")||e.getMessage().contains("Bad credentials")){
                      throw new UsernameNotFoundException("用户名或密码错误");
                    }
              
        }
        return fromToken(jwtTokenResp);

    }


    @Override
    public LoginResult reLogin(String username) {
        //构建rest请求
        HttpHeaders headers=new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        LinkedMultiValueMap<String ,Object> multiValueMap=new LinkedMultiValueMap<>();
        multiValueMap.add("login_type","re_login");
        multiValueMap.add("grant_type","password");
        multiValueMap.add("username",username);
        multiValueMap.add("password","withoutPassword");
        multiValueMap.add("client", client);
        headers.add("Authorization",basicTokeSoccer);

        HttpEntity<LinkedMultiValueMap<String,Object>> entity=new HttpEntity<>(multiValueMap,headers);
        ResponseEntity<JwtToken> jwtTokenResp=null;

        try {
            jwtTokenResp=customRestTemplate.postForEntity(oauth2Url,entity,JwtToken.class);
        }catch (Exception e){
            log.info("重新登录失败！"+e.getMessage());
            e.printStackTrace();
            return null;
        }

        return fromToken(jwtTokenResp);
    }


    @Override
	public boolean registry(LoginOrRegistryForm form) {
        try {
            User user = new User();
            user.setUsername(form.getUsername());
            user.setPassword(new BCryptPasswordEncoder().encode(form.getPassword()));
            user.setEmail(form.getEmail());
            user.setPhone(form.getMobile());
            user.setAliPay(form.getAliPay());
            user.setWeChat(form.getWeChat());
            user.setQq(form.getQq());
            mongoOperations.save(user);
            return true;
        }catch (Exception e){
            return  false;
        }

	}




	@Override
	public boolean logout(HttpServletRequest request) {
		// TODO Auto-generated method stub
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (token != null) {
            long expiredSec= JwtUtil.getExpiredSeconds(token);
            long exp=(expiredSec-System.currentTimeMillis()/1000);
            redisTemplate.opsForValue().set(Consts.Redis_Token_Black_List_Prefix+token, "",exp ,TimeUnit.SECONDS);
        }
		return true;
	}

	private LoginResult fromToken(ResponseEntity<JwtToken> jwtTokenResp){

        //处理 token
        try {

            JwtToken jwtToken=jwtTokenResp.getBody();
            assert jwtToken != null;
            //token string
            String token=jwtToken.getAccessToken();
            String refreshToken=jwtToken.getRefreshToken();
            log.info("成功获取token");

            //解析token,转换成json object
            String tokenStr= JwtHelper.decode(token).getClaims();
            JSONObject tokenJsonObj= JSON.parseObject(tokenStr);

            //取数
            String userId=tokenJsonObj.getString("id");
            String username=tokenJsonObj.getString("username");
            JSONArray jsonArray=tokenJsonObj.getJSONArray("authorities");

            List<String> authorities=new ArrayList<>();
            if(jsonArray!=null) {
                authorities = jsonArray.stream().map(Object::toString).collect(Collectors.toList());
            }else {
                authorities.add("Guest");
            }
            // 1 将该token 存储在redis 里面，配置我们的网关做jwt验证的操作
            // redisTemplate.opsForValue().set(token,"",jwtToken.getExpiresIn(), TimeUnit.SECONDS);
            LoginResult lr=new LoginResult();
            lr.setToken(jwtToken.getTokenType()+" "+token);
            lr.setAuthorities(authorities);
            lr.setUserId(userId);
            lr.setUsername(username);

            return lr;

        }catch (Exception e){
            return  null;
        }

    }

}
